
#include "GAPopulation.h"

bool cmpGenome(GAGenome *a, GAGenome *b) 
   {
    return a->evaluate() > b->evaluate() ;
   }

void GAPopulation::stats()
	{
	fitSum = 0;
	fitAve = 0;
	fitMin = 999999;
	fitMax = -999999;
	for (unsigned int i=0; i<indiv.size(); i++) 
		{
		float fit = indiv[i]->evaluate();
		fitSum += fit;
		if (fit > fitMax) fitMax = fit;
		if (fit < fitMin) fitMin = fit;
		}
	fitAve = fitSum / indiv.size();
	}

#ifndef USE_MPI
void GAPopulation::evaluate()
	{
	fitSum = 0;
	fitAve = 0;
	fitMin = 999999;
	fitMax = -999999;
	for (unsigned int i=0; i<indiv.size(); i++) 
		{
		float fit = indiv[i]->evaluate();
		fitSum += fit;
		if (fit > fitMax) fitMax = fit;
		if (fit < fitMin) fitMin = fit;
		}
	fitAve = fitSum / indiv.size();
	}
#else
void GAPopulation::evaluate()
	{
	fitSum = 0;
	fitAve = 0;
	fitMin = 999999;
	fitMax = -999999;

	int myid , numprocs;
	MPI_Comm_size ( MPI_COMM_WORLD ,& numprocs );
	MPI_Comm_rank ( MPI_COMM_WORLD ,& myid );

	float fitness_all[MAX_POP_SIZE];
	float fitness[MAX_POP_SIZE];
	memset(fitness_all, 0, sizeof(float)*MAX_POP_SIZE);
	memset(fitness, 0, sizeof(float)*MAX_POP_SIZE);
	assert(indiv.size() % numprocs == 0);
	int numIndiv = indiv.size() / numprocs;

	unsigned int start = myid*numIndiv;
        unsigned int end = start + numIndiv;
	for (unsigned int i=start; i<end && i<indiv.size(); i++) {
		fitness[i] = indiv[i]->evaluate();
		}

	int err = MPI_Gather(&fitness[start], numIndiv, MPI_FLOAT, 
			      fitness_all, numIndiv, 
			      MPI_FLOAT, 0, MPI_COMM_WORLD);
	assert (err == MPI_SUCCESS);	
	MPI_Bcast(fitness_all, indiv.size(), MPI_FLOAT, 0, MPI_COMM_WORLD);

	for (unsigned int i=0; i<indiv.size(); i++) 
		{
		float fit = (float)fitness_all[i];
		indiv[i]->evaluate(fit);
		fitSum += fit;
		if (fit > fitMax) fitMax = fit;
		if (fit < fitMin) fitMin = fit;
		}

	fitAve = fitSum / indiv.size();
	}
#endif


GAPopulation::GAPopulation(const GAGenome *c, unsigned int popsize) 
   {
	initialize(c, popsize);
	evaluate();
	sort();
   }

GAPopulation::GAPopulation(unsigned int popsize) 
   {
   fitSum = 0;
   fitAve = 0;
   fitMin = 999;
   fitMax = -999;
   indiv.clear();
   indiv.resize(popsize);
   }

void GAPopulation::initialize(const GAGenome *c, unsigned int popsize) 
   {
   if (popsize > MAX_POP_SIZE)
	{
	cerr << "popsize exceeds maximum" << endl;
	exit(1);
	}

   fitSum = 0;
   fitAve = 0;
   fitMin = 999;
   fitMax = -999;
   indiv.clear();
   for (unsigned int i=0; i<popsize; i++)
	{
	GAGenome* cc = (GAGenome*) c->clone();
	cc->initialize();
	indiv.push_back(cc);
	}
   }

